package cn.buk.tms.flight.dao;

import cn.buk.common.sc.CommonSearchCriteria;
import cn.buk.tms.dao.AbstractDao;
import cn.buk.tms.entity.misc.CustomerFlightDiscount;
import cn.buk.tms.entity.misc.FlightKeyCustomerPolicy;
import cn.buk.common.util.DateUtil;
import cn.buk.tms.entity.misc.FlightKeyCustomerPolicy_;
import jakarta.persistence.criteria.*;
import org.springframework.stereotype.Repository;

import jakarta.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;

/**
 * @author yfdai
 */
@Repository
@Transactional
public class KeyCustomerPolicyDaoImpl extends AbstractDao implements KeyCustomerPolicyDao {


  @Override
  public int saveKeyCustomerPolicy(FlightKeyCustomerPolicy keyCustomerPolicy) {
    if (keyCustomerPolicy.getId() == 0) {
      em.persist(keyCustomerPolicy);
    } else {
      keyCustomerPolicy.setLastUpdate(DateUtil.getCurDateTime());
      em.merge(keyCustomerPolicy);
    }

    return keyCustomerPolicy.getId();
  }

  private List<Predicate> buildPredicates_search(CriteriaBuilder cb, Root<FlightKeyCustomerPolicy> root, int enterpriseId, CommonSearchCriteria sc) {
    List<Predicate> predicates = new ArrayList<>();

    Predicate predicate = cb.conjunction();
    predicates.add(predicate);

    predicate = cb.equal(root.get(FlightKeyCustomerPolicy_.enterpriseId), enterpriseId);
    predicates.add(predicate);

    if (sc.getStatus() == 0) {
      predicate = cb.equal(root.get(FlightKeyCustomerPolicy_.status), 0);
    } else if (sc.getStatus() == 1) {
      predicate = cb.equal(root.get(FlightKeyCustomerPolicy_.status), 1);
    }
    predicates.add(predicate);

    if (sc.getCarrier() != null && sc.getCarrier().trim().length() == 2) {
      predicate = cb.equal(root.get(FlightKeyCustomerPolicy_.carrier), sc.getCarrier().toUpperCase());
      predicates.add(predicate);
    }

    return predicates;
  }

  @Override
  public List<FlightKeyCustomerPolicy> search(int enterpriseId, CommonSearchCriteria sc) {
    List<FlightKeyCustomerPolicy> results = null;

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<FlightKeyCustomerPolicy> cq = cb.createQuery(FlightKeyCustomerPolicy.class);
    Root<FlightKeyCustomerPolicy> root = cq.from(FlightKeyCustomerPolicy.class);
    root.alias("o");

    var predicates0 = buildPredicates_search(cb, root, enterpriseId, sc);



    //计算根据条件查询得出的数据总数
    CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
    Root<FlightKeyCustomerPolicy> countRoot = countQuery.from(FlightKeyCustomerPolicy.class);
    countRoot.alias("o");

    var predicates1 = buildPredicates_search(cb, countRoot, enterpriseId, sc);

    // count items
    countQuery.select(cb.count(countRoot)).where(predicates1.toArray(new Predicate[predicates1.size()]));
    Long count = em.createQuery(countQuery).getSingleResult();

    //查询
    cq.select(root).where(predicates0.toArray(new Predicate[predicates0.size()]));

    List<Order> orderByes = new ArrayList<>();
    if (sc.getOrderBy() == 0) {
      //默认排序
      orderByes.add(cb.desc(root.get("status")));
      orderByes.add(cb.asc(root.get("carrier")));
    } else if (sc.getOrderBy() == 1) {
      //失效日期降序
      orderByes.add(cb.desc(root.get("expireDate")));
    } else if (sc.getOrderBy() == 2) {
      //生效日期降序
      orderByes.add(cb.desc(root.get("effectDate")));
    } else if (sc.getOrderBy() == 4) {
      //失效日期升序
      orderByes.add(cb.asc(root.get("expireDate")));
    } else if (sc.getOrderBy() == 8) {
      //生效日期升序
      orderByes.add(cb.asc(root.get("effectDate")));
    }

    cq.orderBy(orderByes);

    int maxResults = count.intValue();
    if (maxResults > 0) {
      sc.getPage().setRowCount(maxResults);

      results = em.createQuery(cq)
              .setFirstResult(sc.getPage().getFirstPosition())
              .setMaxResults(sc.getPage().getPageSize())
              .getResultList();
    }

    return results == null ? new ArrayList<>(): results;
  }

  @Override
  public List<FlightKeyCustomerPolicy> search(int enterpriseId, String carrier) {
    return em.createQuery("select o from FlightKeyCustomerPolicy o " +
            "where o.enterpriseId = :enterpriseId " +
            "and o.carrier = :carrier " +
            "and o.status = 1 and o.effectDate <= :today and o.expireDate >= :today", FlightKeyCustomerPolicy.class)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("carrier", carrier)
            .setParameter("today", DateUtil.getCurDate())
            .getResultList();
  }

  @Override
  public FlightKeyCustomerPolicy searchFlightKeyCustomerPolicy(int enterpriseId, String policyCode) {
    List<FlightKeyCustomerPolicy> list = em.createQuery("select o from FlightKeyCustomerPolicy o " +
            "where o.enterpriseId = :enterpriseId and o.policyCode = :policyCode", FlightKeyCustomerPolicy.class)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("policyCode", policyCode)
            .getResultList();

    return list.size() == 1 ? list.get(0): null;
  }

  @Override
  public CustomerFlightDiscount searchCustomerFlightDiscount(int enterpriseId, int customerEnterpriseId, String policyCode) {
    List<CustomerFlightDiscount> list = em.createQuery("select o from CustomerFlightDiscount o " +
            "where o.enterpriseId = :enterpriseId " +
            "and o.customerEnterpriseId = :customerEnterpriseId " +
            "and o.policyCode = :policyCode", CustomerFlightDiscount.class)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("customerEnterpriseId", customerEnterpriseId)
            .setParameter("policyCode", policyCode)
            .getResultList();

    return list.size() == 1 ? list.get(0): null;
  }

  @Override
  public List<FlightKeyCustomerPolicy> searchFlightKeyCustomerPolicyByKeyCustomerNo(int enterpriseId, String keyCustomerNo) {
    return em.createQuery("select o from FlightKeyCustomerPolicy o " +
                    "where o.enterpriseId = :enterpriseId and " +
                    "(o.keyCustomerCode = :keyCustomerNo or o.rawKeyCustomerCode = :keyCustomerNo)", FlightKeyCustomerPolicy.class)
            .setParameter("enterpriseId", enterpriseId)
            .setParameter("keyCustomerNo", keyCustomerNo)
            .getResultList();
  }
}
